#include "AST.h"
class Scope
{
public:
  BasicBlock *block;
  bool hasReturn;
  std::map<std::string,AllocaInst *>locals;
  std::map<std::string,std::string>types;
  std::map<std::string,bool>isFuncArg;
};
class ScopeContext{
private:
  std::vector<Scope *>scopeStack;
public:
  AllocaInst* getSymbolValue(std::string name){
      for(auto it = scopeStack.rbegin();it != scopeStack.rend();it++){
          if((*it)->locals.find(name) != (*it)->locals.end())
             return (*it)->locals[name];
      }
      return nullptr;
  }
  std::string getSymbolType(std::string name){
      for(auto it = scopeStack.rbegin();it != scopeStack.rend();it++){
          if((*it)->types.find(name) != (*it)->types.end())
             return (*it)->types[name];
      }
      return 0;
  }
  bool isFuncArg(std::string name){
      for(auto it = scopeStack.rbegin();it != scopeStack.rend();it++){
          if((*it)->isFuncArg.find(name) != (*it)->isFuncArg.end())
             return (*it)->isFuncArg[name];
      }
      return false;
  }
  void setSymbol(std::string name,AllocaInst* alloca,std::string type,bool isArg){
      scopeStack.back()->locals[name] = alloca;
      scopeStack.back()->types[name] = type;
      scopeStack.back()->isFuncArg[name] = isArg;
  }
  BasicBlock *currentBlock()const{
      return scopeStack.back()->block;
  }
  void setCurrentBlock(BasicBlock *block){
      scopeStack.back()->block = block;
  }
  void pushBlock(BasicBlock *block){
      Scope * scope = new Scope();
      scope->block = block;
      scope->hasReturn = false;
      scopeStack.push_back(scope);
  }
  void popBlock(){
      Scope *scope = scopeStack.back();
      scopeStack.pop_back();
      delete scope;
  }
  bool hasReturn(){
      return scopeStack.back()->hasReturn;
  }
  void setReturn(bool hasReturn){
      scopeStack.back()->hasReturn = hasReturn;
  }
};
